#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>

static int inited = 0;
static void* (*real_malloc)(size_t) = NULL;
static void* (*real_free)(void*) = NULL;
static int log_fd = -1;

struct log_entry {
	long action;
	long ptr;
	long size;
};

static void init()
{
	if (inited)
		return;

	real_malloc  = dlsym(RTLD_NEXT, "malloc");
	if (!real_malloc) {
		fprintf(stderr, "unable to get malloc symbol!\n");
		exit(1);
	}

	real_free = dlsym(RTLD_NEXT, "free");
	if (!real_free) {
		fprintf(stderr, "unable to get free symbol!\n");
		exit(1);
	}

	log_fd = open("memhook.log", O_CREAT | O_TRUNC | O_WRONLY, 0644);
	if (log_fd == -1) {
		fprintf(stderr, "unable to open memhook.log!\n");
		exit(1);
	}

	inited = 1;

	//fprintf(stderr, "memhook.so: successfully loaded!\n");
}

void* malloc(size_t size)
{
	if (!inited) {
		init();
	}
	void* ret = real_malloc(size);

	struct log_entry entry = {0, (long)ret, size};
	write(log_fd, &entry, sizeof(entry));
	return ret;
}

void free(void* ptr)
{
	if (!inited) {
		init();
	}
	real_free(ptr);

	if (ptr == NULL) {
		return;
	}

	struct log_entry entry = {1, (long)ptr, 0};
	write(log_fd, &entry, sizeof(entry));
}
